home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / indentsr / parse.c < prev    next >
C/C++ Source or Header  |  1990-01-04  |  9KB  |  310 lines

  1. /*
  2.  * Copyright (c) 1985 Sun Microsystems, Inc.
  3.  * Copyright (c) 1980 The Regents of the University of California.
  4.  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms are permitted
  8.  * provided that the above copyright notice and this paragraph are
  9.  * duplicated in all such forms and that any documentation,
  10.  * advertising materials, and other materials related to such
  11.  * distribution and use acknowledge that the software was developed
  12.  * by the University of California, Berkeley, the University of Illinois,
  13.  * Urbana, and Sun Microsystems, Inc.  The name of either University
  14.  * or Sun Microsystems may not be used to endorse or promote products
  15.  * derived from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #ifndef lint
  22. static char sccsid[] = "@(#)parse.c    5.8 (Berkeley) 9/15/88";
  23. #endif /* not lint */
  24.  
  25. #include "indent_globs.h"
  26. #include "indent_codes.h"
  27.  
  28.  
  29.  
  30.  
  31. parse(tk)
  32.     int         tk;        /* the code for the construct scanned */
  33. {
  34.     int         i;
  35.  
  36. #ifdef debug
  37.     printf("%2d - %s\n", tk, token);
  38. #endif
  39.  
  40.     while (ps.p_stack[ps.tos] == ifhead && tk != elselit) {
  41.     /* true if we have an if without an else */
  42.     ps.p_stack[ps.tos] = stmt;    /* apply the if(..) stmt ::= stmt
  43.                      * reduction */
  44.     reduce();        /* see if this allows any reduction */
  45.     }
  46.  
  47.  
  48.     switch (tk) {        /* go on and figure out what to do with the
  49.                  * input */
  50.  
  51.     case decl:            /* scanned a declaration word */
  52.     ps.search_brace = btype_2;
  53.     /* indicate that following brace should be on same line */
  54.     if (ps.p_stack[ps.tos] != decl) {    /* only put one declaration
  55.                          * onto stack */
  56.         break_comma = true;    /* while in declaration, newline should be
  57.                  * forced after comma */
  58.         ps.p_stack[++ps.tos] = decl;
  59.         ps.il[ps.tos] = ps.i_l_follow;
  60.  
  61.         if (ps.ljust_decl) {/* only do if we want left justified
  62.                  * declarations */
  63.         ps.ind_level = 0;
  64.         for (i = ps.tos - 1; i > 0; --i)
  65.             if (ps.p_stack[i] == decl)
  66.             ++ps.ind_level;    /* indentation is number of
  67.                      * declaration levels deep we are */
  68.         ps.i_l_follow = ps.ind_level;
  69.         }
  70.     }
  71.     break;
  72.  
  73.     case ifstmt:        /* scanned if (...) */
  74.     if (ps.p_stack[ps.tos] == elsehead && ps.else_if)    /* "else if ..." */
  75.         ps.i_l_follow = ps.il[ps.tos];
  76.     case dolit:        /* 'do' */
  77.     case forstmt:        /* for (...) */
  78.     ps.p_stack[++ps.tos] = tk;
  79.     ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
  80.     ++ps.i_l_follow;    /* subsequent statements should be indented 1 */
  81.     ps.search_brace = btype_2;
  82.     break;
  83.  
  84.     case lbrace:        /* scanned { */
  85.     break_comma = false;    /* don't break comma in an initial list */
  86.     if (ps.p_stack[ps.tos] == stmt || ps.p_stack[ps.tos] == decl
  87.         || ps.p_stack[ps.tos] == stmtl)
  88.         ++ps.i_l_follow;    /* it is a random, isolated stmt group or a
  89.                  * declaration */
  90.     else {
  91.         if (s_code == e_code) {
  92.         /*
  93.          * only do this if there is nothing on the line
  94.          */
  95.         --ps.ind_level;
  96.         /*
  97.          * it is a group as part of a while, for, etc.
  98.          */
  99.         if (ps.p_stack[ps.tos] == swstmt && ps.case_indent >= 1)
  100.             --ps.ind_level;
  101.         /*
  102.          * for a switch, brace should be two levels out from the code
  103.          */
  104.         }
  105.     }
  106.  
  107.     ps.p_stack[++ps.tos] = lbrace;
  108.     ps.il[ps.tos] = ps.ind_level;
  109.     ps.p_stack[++ps.tos] = stmt;
  110.     /* allow null stmt between braces */
  111.     ps.il[ps.tos] = ps.i_l_follow;
  112.     break;
  113.  
  114.     case whilestmt:        /* scanned while (...) */
  115.     if (ps.p_stack[ps.tos] == dohead) {
  116.         /* it is matched with do stmt */
  117.         ps.ind_level = ps.i_l_follow = ps.il[ps.tos];
  118.         ps.p_stack[++ps.tos] = whilestmt;
  119.         ps.il[ps.tos] = ps.ind_level = ps.i_l_follow;
  120.     }
  121.     else {            /* it is a while loop */
  122.         ps.p_stack[++ps.tos] = whilestmt;
  123.         ps.il[ps.tos] = ps.i_l_follow;
  124.         ++ps.i_l_follow;
  125.         ps.search_brace = btype_2;
  126.     }
  127.  
  128.     break;
  129.  
  130.     case elselit:        /* scanned an else */
  131.  
  132.     if (ps.p_stack[ps.tos] != ifhead)
  133.         diag(1, "Unmatched 'else'");
  134.     else {
  135.         ps.ind_level = ps.il[ps.tos];    /* indentation for else should
  136.                          * be same as for if */
  137.         ps.i_l_follow = ps.ind_level + 1;    /* everything following should
  138.                          * be in 1 level */
  139.         ps.p_stack[ps.tos] = elsehead;
  140.         /* remember if with else */
  141.         ps.search_brace = btype_2 | ps.else_if;
  142.     }
  143.     break;
  144.  
  145.     case rbrace:        /* scanned a } */
  146.     /* stack should have <lbrace> <stmt> or <lbrace> <stmtl> */
  147.     if (ps.p_stack[ps.tos - 1] == lbrace) {
  148.         ps.ind_level = ps.i_l_follow = ps.il[--ps.tos];
  149.         ps.p_stack[ps.tos] = stmt;
  150.     }
  151.     else
  152.         diag(1, "Stmt nesting error.");
  153.     break;
  154.  
  155.     case swstmt:        /* had switch (...) */
  156.     ps.p_stack[++ps.tos] = swstmt;
  157.     ps.cstk[ps.tos] = case_ind;
  158.     /* save current case indent level */
  159.     ps.il[ps.tos] = ps.i_l_follow;
  160.     case_ind = ps.i_l_follow + ps.case_indent;    /* cases should be one
  161.                              * level down from
  162.                              * switch */
  163.     ps.i_l_follow += ps.case_indent + 1;    /* statements should be two
  164.                          * levels in */
  165.     ps.search_brace = btype_2;
  166.     break;
  167.  
  168.     case semicolon:        /* this indicates a simple stmt */
  169.     break_comma = false;    /* turn off flag to break after commas in a
  170.                  * declaration */
  171.     ps.p_stack[++ps.tos] = stmt;
  172.     ps.il[ps.tos] = ps.ind_level;
  173.     break;
  174.  
  175.     default:            /* this is an error */
  176.     diag(1, "Unknown code to parser");
  177.     return;
  178.  
  179.  
  180.     }                /* end of switch */
  181.  
  182.     reduce();            /* see if any reduction can be done */
  183.  
  184. #ifdef debug
  185.     for (i = 1; i <= ps.tos; ++i)
  186.     printf("(%d %d)", ps.p_stack[i], ps.il[i]);
  187.     printf("\n");
  188. #endif
  189.  
  190.     return;
  191. }
  192.  
  193. /*
  194.  * Copyright (C) 1976 by the Board of Trustees of the University of Illinois
  195.  * 
  196.  * All rights reserved
  197.  * 
  198.  * 
  199.  * NAME: reduce
  200.  * 
  201.  * FUNCTION: Implements the reduce part of the parsing algorithm
  202.  * 
  203.  * ALGORITHM: The following reductions are done.  Reductions are repeated until
  204.  * no more are possible.
  205.  * 
  206.  * Old TOS        New TOS <stmt> <stmt>    <stmtl> <stmtl> <stmt>    <stmtl> do
  207.  * <stmt>    "dostmt" if <stmt>    "ifstmt" switch <stmt>    <stmt> decl
  208.  * <stmt>    <stmt> "ifelse" <stmt>    <stmt> for <stmt>    <stmt> while
  209.  * <stmt>    <stmt> "dostmt" while    <stmt>
  210.  * 
  211.  * On each reduction, ps.i_l_follow (the indentation for the following line) is
  212.  * set to the indentation level associated with the old TOS.
  213.  * 
  214.  * PARAMETERS: None
  215.  * 
  216.  * RETURNS: Nothing
  217.  * 
  218.  * GLOBALS: ps.cstk ps.i_l_follow = ps.il ps.p_stack = ps.tos =
  219.  * 
  220.  * CALLS: None
  221.  * 
  222.  * CALLED BY: parse 
  223.  * 
  224.  * HISTORY: initial coding     November 1976    D A Willcox of CAC
  225.  * 
  226.  */
  227. /*----------------------------------------------*\
  228. |   REDUCTION PHASE                    |
  229. \*----------------------------------------------*/
  230. reduce()
  231. {
  232.  
  233.     register int i;
  234.  
  235.     for (;;) {            /* keep looping until there is nothing left to
  236.                  * reduce */
  237.  
  238.     switch (ps.p_stack[ps.tos]) {
  239.  
  240.     case stmt:
  241.         switch (ps.p_stack[ps.tos - 1]) {
  242.  
  243.         case stmt:
  244.         case stmtl:
  245.         /* stmtl stmt or stmt stmt */
  246.         ps.p_stack[--ps.tos] = stmtl;
  247.         break;
  248.  
  249.         case dolit:    /* <do> <stmt> */
  250.         ps.p_stack[--ps.tos] = dohead;
  251.         ps.i_l_follow = ps.il[ps.tos];
  252.         break;
  253.  
  254.         case ifstmt:
  255.         /* <if> <stmt> */
  256.         ps.p_stack[--ps.tos] = ifhead;
  257.         for (i = ps.tos - 1;
  258.             (
  259.              ps.p_stack[i] != stmt
  260.              &&
  261.              ps.p_stack[i] != stmtl
  262.              &&
  263.              ps.p_stack[i] != lbrace
  264.              );
  265.             --i);
  266.         ps.i_l_follow = ps.il[i];
  267.         /*
  268.          * for the time being, we will assume that there is no else on
  269.          * this if, and set the indentation level accordingly. If an
  270.          * else is scanned, it will be fixed up later
  271.          */
  272.         break;
  273.  
  274.         case swstmt:
  275.         /* <switch> <stmt> */
  276.         case_ind = ps.cstk[ps.tos - 1];
  277.  
  278.         case decl:        /* finish of a declaration */
  279.         case elsehead:
  280.         /* <<if> <stmt> else> <stmt> */
  281.         case forstmt:
  282.         /* <for> <stmt> */
  283.         case whilestmt:
  284.         /* <while> <stmt> */
  285.         ps.p_stack[--ps.tos] = stmt;
  286.         ps.i_l_follow = ps.il[ps.tos];
  287.         break;
  288.  
  289.         default:        /* <anything else> <stmt> */
  290.         return;
  291.  
  292.         }            /* end of section for <stmt> on top of stack */
  293.         break;
  294.  
  295.     case whilestmt:    /* while (...) on top */
  296.         if (ps.p_stack[ps.tos - 1] == dohead) {
  297.         /* it is termination of a do while */
  298.         ps.p_stack[--ps.tos] = stmt;
  299.         break;
  300.         }
  301.         else
  302.         return;
  303.  
  304.     default:        /* anything else on top */
  305.         return;
  306.  
  307.     }
  308.     }
  309. }
  310.